#include "SQLCharacterDataType.h"

#include "../../../utils/FnvHash.h"
#include "../../../utils/Types.h"
#include "../../../utils/listAddAll.h"

#include "../expr/SQLIntegerExpr.h"

string_ptr SQLCharacterDataType::CHAR_TYPE_BYTE = make_string_ptr("BYTE");
string_ptr SQLCharacterDataType::CHAR_TYPE_CHAR = make_string_ptr("CHAR");

SQLCharacterDataType::SQLCharacterDataType(string_ptr name) : SQLDataTypeImpl(name)
{
  hints = std::make_shared<std::list<SQLCommentHint_ptr>>();
}

// SQLCharacterDataType::SQLCharacterDataType(string_ptr  name, int precision)
// {
//   SQLDataTypeImpl(name);
//   this->addArgument(new SQLIntegerExpr(precision));
// }

string_ptr SQLCharacterDataType::getCharSetName()
{
  return charSetName;
}

void SQLCharacterDataType::setCharSetName(string_ptr charSetName)
{
  this->charSetName = charSetName;
}

BOOL_ptr SQLCharacterDataType::isHasBinary()
{
  return hasBinary;
}

void SQLCharacterDataType::setHasBinary(BOOL_ptr hasBinary)
{
  this->hasBinary = hasBinary;
}

string_ptr SQLCharacterDataType::getCollate()
{
  return collate;
}

void SQLCharacterDataType::setCollate(string_ptr collate)
{
  this->collate = collate;
}

string_ptr SQLCharacterDataType::getCharType()
{
  return charType;
}

void SQLCharacterDataType::setCharType(string_ptr charType)
{
  this->charType = charType;
}

SQLCommentHint_list_ptr SQLCharacterDataType::getHints()
{
  return hints;
}

void SQLCharacterDataType::setHints(SQLCommentHint_list_ptr hints)
{
  this->hints->clear(); // = hints;
  Utils::ListAddAll<SQLCommentHint, SQLCommentHint>(hints, this->hints);
}

// int getLength() {
//     if (this->arguments.size() == 1) {
//         SQLExpr_ptr arg = this->arguments->get(0);
//         if (arg instanceof SQLIntegerExpr) {
//             return ((SQLIntegerExpr) arg).getNumber().intValue();
//         }
//     }

//     return -1;
// }

// void accept0(SQLASTVisitor* visitor) {
//     if (visitor->visit(this)) {
//         for (int i = 0; i < arguments->size(); i++) {
//             SQLExpr_ptr arg = arguments->get(i);
//             if (arg != NULL) {
//                 arg->accept(visitor);
//             }
//         }
//     }

//     visitor->endVisit(this);
// }

SQLObject_ptr SQLCharacterDataType::clone()
{
  SQLObject_ptr clone_tmp = SQLCharacterDataType_ptr(new SQLCharacterDataType(getName()));
  SQLCharacterDataType_ptr x = std::dynamic_pointer_cast<SQLCharacterDataType>(clone_tmp);
  // SQLCharacterDataType *x = new SQLCharacterDataType(getName());

  SQLDataTypeImpl::cloneTo(x);

  x->charSetName = charSetName;
  x->collate = collate;
  x->charType = charType;
  x->hasBinary = hasBinary;

  return x;
}

// string_ptr  toString() {
//     return SQLUtils.toSQLString(this);
// }

int SQLCharacterDataType::jdbcType()
{
  long nameNash = nameHashCode64();

  if (nameNash == FnvHash::Constants::NCHAR)
  {
    return Types::NCHAR;
  }

  if (nameNash == FnvHash::Constants::CHAR || nameNash == FnvHash::Constants::JSON)
  {
    return Types::CHAR;
  }

  if (nameNash == FnvHash::Constants::VARCHAR || nameNash == FnvHash::Constants::VARCHAR2 || nameNash == FnvHash::Constants::STRING)
  {
    return Types::VARCHAR;
  }

  if (nameNash == FnvHash::Constants::NVARCHAR || nameNash == FnvHash::Constants::NVARCHAR2)
  {
    return Types::NVARCHAR;
  }

  return Types::OTHER;
}
